/* Copyright 2010 by Matt Van Der Westhuizen */

package org.chaoticengine.ast;

import java.util.ArrayList;
import org.chaoticengine.ast.model.World;
import org.chaoticengine.ast.model.WorldMap;
import org.chaoticengine.ast.pattern.ViewController;
import org.chaoticengine.ast.view.MiniMapView;
import org.chaoticengine.ast.view.SelectionView;
import org.chaoticengine.ast.view.TileFactory;
import org.chaoticengine.ast.view.TimeView;
import org.chaoticengine.ast.view.WorldMapView;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

/**
 *
 * @author Matt Van Der Westhuizen <mattpwest@gmail.com>
 */
public class WorldState extends BasicGameState {
    protected WorldMap map = null;
    protected ArrayList<ViewController> views = new ArrayList<ViewController>();

    @Override
    public int getID() {
        return(GameStateId.WORLD.ordinal());
    }

    @Override
    public void enter(GameContainer container, StateBasedGame game) throws SlickException {
        // Get global data
        GlobalData gd = GlobalData.getInstance();
        map = gd.getMap();

        // Create views
        //// Map view (main view)
        Rectangle mapViewRect = new Rectangle(0, 0, container.getWidth() / 4 * 3,
                container.getWidth() / 4 * 3);

        WorldMapView mapView = new WorldMapView();
        mapView.setPosition(new Vector2f(0.0f, 0.0f));
        mapView.setBoundingRectangle(mapViewRect);
        mapView.setViewport(mapViewRect);
        mapView.setScrollDistance(TileFactory.getInstance().getTileWidth() * 10);

        map.addObserver(mapView);
        views.add(mapView);

        //// Time view shows the current date & time
        TimeView timeView = new TimeView();
        timeView.setPosition(new Vector2f(container.getWidth() / 4 * 3 + 1, 1));
        timeView.setBoundingRectangle(new Rectangle(0, 0, 
                container.getWidth() / 4, 16));
        gd.getWorld().addObserver(timeView);

        views.add(timeView);

        //// Mini-map view
        MiniMapView miniMapView = new MiniMapView();
        miniMapView.setPosition(new Vector2f(container.getWidth() / 4 * 3 + 1, 1 + 16));
        miniMapView.setBoundingRectangle(new Rectangle(0, 0, 
                container.getWidth() / 4,
                container.getHeight() / 3));
        miniMapView.setCamera(mapView.getCamera());

        map.addObserver(miniMapView);
        views.add(miniMapView);

        //// Selection view - shows details about selected item
        SelectionView sv = new SelectionView();
        sv.setPosition(new Vector2f(container.getWidth() / 4 * 3,
                container.getHeight() / 3 + 16 + 1));
        sv.setBoundingRectangle(new Rectangle(0, 0, 
                container.getWidth() / 4,
                container.getHeight() / 3 * 2));

        gd.addObserver(sv);
        views.add(sv);
    }



    public void init(GameContainer gc, StateBasedGame sbg) throws SlickException {
        GlobalData gd = GlobalData.getInstance();
        TileFactory.getInstance("data/tilesets/" + gd.getConfig("tileset") + ".xml");
        TileFactory.getInstance().loadAllImages();
    }

    public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).update(gc, sbg, delta);
        }
    }

    public void render(GameContainer gc, StateBasedGame sbg, Graphics grphcs) throws SlickException {
        grphcs.setColor(Color.darkGray);
        grphcs.fillRect(0, 0, gc.getWidth(), gc.getHeight());

        for (int i = 0; i < views.size(); i++) {
            views.get(i).render(gc, sbg, grphcs);
        }
    }

    @Override
    public void keyPressed(int key, char c) {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).keyPressed(key, c);
        }
    }

    @Override
    public void keyReleased(int key, char c) {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).keyReleased(key, c);
        }
    }

    @Override
    public void mouseMoved(int oldx, int oldy, int newx, int newy) {
        for (int i = 0; i < views.size(); i++) {
            ViewController v = views.get(i);

            if ((!v.getBoundingRectangle().contains(oldx, oldy)) &&
                    (v.getBoundingRectangle().contains(newx, newy))) {
                v.onMouseEnter();
            } else if ((v.getBoundingRectangle().contains(oldx, oldy)) &&
                    (!v.getBoundingRectangle().contains(newx, newy))) {
                v.onMouseExit();
            } else if ((v.getBoundingRectangle().contains(newx, newy)) &&
                    (!v.hasFocus())){
                // Oops should be focused
                v.onMouseEnter();
            }

            v.onMouseMove(oldx, oldy, newx, newy);
        }
    }

    @Override
    public void mousePressed(int button, int x, int y) {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).onMouseClick(x, y, button);
        }
    }

    @Override
    public void mouseReleased(int button, int x, int y) {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).onMouseRelease(x, y, button);
        }
    }

    @Override
    public void mouseWheelMoved(int newValue) {
        for (int i = 0; i < views.size(); i++) {
            if (newValue < 0) {
                views.get(i).onMouseWheelDown();
            } else if (newValue > 0) {
                views.get(i).onMouseWheelUp();
            }
        }
    }

    @Override
    public void mouseDragged(int oldx, int oldy, int newx, int newy) {
        for (int i = 0; i < views.size(); i++) {
            views.get(i).onMouseMove(oldx, oldy, newx, newy);
        }
    }
}
